package com.feeyo.prophet.controller;

import com.feeyo.prophet.config.SseClientConfig;
import com.feeyo.prophet.plugins.Md5Util;
import com.feeyo.prophet.pojo.dto.QuestionDTO;
import com.feeyo.prophet.pojo.enums.ResultEnum;
import com.feeyo.prophet.service.BrainV1Service;
import com.google.common.collect.Maps;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.MongoOperations;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Map;


@Slf4j
@RequestMapping("api/chat")
@RestController
public class ChatController {
    private final BrainV1Service brainV1Service;
    private final SseClientConfig sseClientConfig;
    // 确保你的类中包含以下字段
    private final MongoOperations mongoOperations;

    @Autowired
    public ChatController(BrainV1Service brainV1Service, SseClientConfig sseClientConfig, MongoOperations mongoOperations) {
        this.brainV1Service = brainV1Service;
        this.sseClientConfig = sseClientConfig;
        this.mongoOperations = mongoOperations;
    }

    @PostMapping(value = "dialogue", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter dialogue(@RequestHeader(defaultValue = "") String appId,
                               @RequestHeader(defaultValue = "") String timestamp,
                               @RequestHeader(defaultValue = "") String token,
                               @RequestBody QuestionDTO questionDTO,
                               HttpServletRequest request) throws IOException {

        String conversationId = questionDTO.getConversationId();
        SseEmitter emitter = new SseEmitter();
        if (StringUtils.isBlank(appId) || StringUtils.isBlank(timestamp) || StringUtils.isBlank(token)) {
            emitter.send(SseEmitter.event().name("error").data(ResultEnum.USER_ILLEGAL_AUTHENTICATION));
            emitter.complete();
            return emitter;
        }
        brainV1Service.dialogue(appId, questionDTO.getInput(), request, conversationId, emitter, false);
        return emitter;
    }

    @PostMapping(value = "v1/dialogue", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter dialogueV1(@RequestHeader(defaultValue = "") String appId,
                                 @RequestHeader(defaultValue = "") String timestamp,
                                 @RequestHeader(defaultValue = "") String token,
                                 @RequestBody QuestionDTO questionDTO,
                                 HttpServletRequest request) throws IOException {

        String conversationId = questionDTO.getConversationId();
        SseEmitter emitter = new SseEmitter();
        if (StringUtils.isBlank(appId) || StringUtils.isBlank(timestamp) || StringUtils.isBlank(token)) {
            emitter.send(SseEmitter.event().name("error").data(ResultEnum.USER_ILLEGAL_AUTHENTICATION));
            emitter.complete();
            return emitter;
        }
        brainV1Service.dialogue(appId, questionDTO, request, conversationId, emitter);
        return emitter;
    }

    /**
     * 先注册,问题记录
     */
    @PostMapping(value = "v1/init", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public ResponseEntity<Map<String, String>> dialogueInit(@RequestHeader(defaultValue = "") String appId,
                                                            @RequestHeader(defaultValue = "") String timestamp,
                                                            @RequestHeader(defaultValue = "") String token,
                                                            @RequestBody QuestionDTO questionDTO) throws IOException {
        SseEmitter emitter = new SseEmitter();
        Map<String, String> response = Maps.newHashMap();
        // 通过客户端ID, 生成唯一ID,目前使用md5
        String uid = Md5Util.generate();

        if (StringUtils.isBlank(appId) || StringUtils.isBlank(timestamp) || StringUtils.isBlank(token)) {
            log.error("Invalid authentication: appId={}, timestamp={}, token={}", appId, timestamp, token);
            emitter.send(SseEmitter.event().name("error").data(ResultEnum.USER_ILLEGAL_AUTHENTICATION));
        }

        log.info("put dialogueInit - uid: {}, time: {}, input: {}", uid, LocalDateTime.now(), questionDTO.getInput());
        // 使用 MongoDB 存储数据
        mongoOperations.upsert(
                Query.query(Criteria.where("_id").is(uid)),
                Update.update("input", questionDTO.getInput()).set("timestamp", LocalDateTime.now()).set("isRunning", false),
                "prophet_chat"
        );
        response.put("uid", uid);
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(response);
    }

    /**
     * 消息 sse处理
     *
     * @param uid            UID 用来代表问题, 一个链接可以有多个问题
     * @param conversationId CID 用来代表用户, 一个用户一个链接
     * @param appId          AID 用来代表授权的应用,标记请求数据源
     */
    @GetMapping(value = "/v1/sseMessage", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter sseMessage(@RequestParam("uid") String uid,
                                 @RequestParam("conversationId") String conversationId,
                                 @RequestParam("appId") String appId,
                                 @RequestParam(value = "isDebug", required = false) String isDebug,
                                 HttpServletRequest request,
                                 HttpServletResponse response) {
        log.info("sseMessage - uid: {}, time: {}, conversationId: {}, appId: {}", uid, LocalDateTime.now(), conversationId, appId);
        // 从 MongoDB 中检索数据
        Query query = Query.query(Criteria.where("_id").is(uid));
        Map<String, Object> document = mongoOperations.findOne(query, Map.class, "prophet_chat");
        String question = document != null ? (String) document.get("input") : null;
        log.info("get Retrieved question: {}", question);
        if (question == null) {
            log.warn("No question found for uid: {}", uid);
            return null;
        }
        SseEmitter emitter = sseClientConfig.getSse(conversationId, response);
        log.info("create SseEmitter success");
        if("true".equals(isDebug)) {
            brainV1Service.dialogue(appId, question, request, conversationId, emitter, true);
        }else{
            brainV1Service.dialogue(appId,question,request,conversationId,emitter,false);
        }


        return emitter;
    }
}